package com.studerb.service;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;

import com.studerb.exceptions.ServiceException;
import com.studerb.service.interfaces.IService;
import com.studerb.service.interfaces.ISettingsService;

/**
 * Wrapper around general java.util.Properties file
 * Maybe add to database later
 */
public class SettingsService implements ISettingsService, IService {
    @Autowired private ClassPathResource settingsResource;
    private Logger logger = Logger.getLogger(SettingsService.class);
    private Properties props;
    private File resourceFile;
    private boolean started = false;
    private boolean settingChanged = false;

    public SettingsService() {
    }

    /**
     * flushes the properties to disk
     * @throws IOException
     */
    public synchronized void flush() {
        try{
            FileOutputStream out = new FileOutputStream(resourceFile);
            logger.debug("Flushing to disk the application properties.");
            props.store(out, "storing properties at " + resourceFile.getName());
            out.close();
        }
        catch(IOException e){
            throw new ServiceException("Error flushing settings: " + e.getMessage(), e);
        }
    }

    /**
     * Wrapper around the properties getProperty
     * @param key
     * @return String value of property
     */
    public String getSetting(String key) {
        return props.getProperty(key);
    }

    @Override public boolean isStarted() {
        return started;
    }

    /**
     * Wrapper around properties setProperty
     * @param key 
     * @param value 
     * @throws IOException
     */
    public synchronized void setSetting(String key, String value) {
        settingChanged = true;
        props.setProperty(key, value);
        flush();
    }

    public void start() {
        if(started)
            throw new RuntimeException("SettingsService Already Started...");
        logger.info("[**SettingsService Starting**]");
        InputStream in;
        try{
            resourceFile = settingsResource.getFile();
            in = new FileInputStream(resourceFile);
            props = new Properties();
            logger.debug("Loading properties from " + resourceFile.getName());
            props.load(in);
            in.close();
            started = true;
        }
        catch(Exception e){
            throw new ServiceException(e.getMessage(), e);
        }
    }

    public void stop() {
        if( !started)
            throw new RuntimeException("SettingsService Already Stopped...");
        logger.info("[**SettingsService Stopping**]");
        if(settingChanged)
            flush();
        started = false;
    }

}
